package hook

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
)

type OnyxIndex struct {
	Image   string   `json:"image"`
	Blocks  []string `json:"blocks"`
	Version string   `json:"version"`
}

// Run is the entrypoint for OCI prestart hook
func Run() error {
	specPath := "/run/containerd/io.containerd.runtime.v2.task/<namespace>/<container_id>/config.json"
	if envPath := os.Getenv("OCI_SPEC_PATH"); envPath != "" {
		specPath = envPath
	}

	spec, err := LoadSpec(specPath)
	if err != nil {
		return fmt.Errorf("load spec failed: %w", err)
	}

	imageName := filepath.Base(spec.Root.Path)
	indexPath := fmt.Sprintf("/etc/onyx/layers/%s.onyxidx.json", imageName)
	index, err := loadIndex(indexPath)
	if err != nil {
		return fmt.Errorf("load index failed: %w", err)
	}

	if err := notifyDaemon(index.Blocks); err != nil {
		return fmt.Errorf("notify daemon failed: %w", err)
	}

	fmt.Printf("[onyx-hook] prefetch %d blocks for %s\n", len(index.Blocks), imageName)
	return nil
}

func loadIndex(path string) (*OnyxIndex, error) {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}
	var idx OnyxIndex
	if err := json.Unmarshal(data, &idx); err != nil {
		return nil, err
	}
	return &idx, nil
}

func notifyDaemon(blocks []string) error {
	url := "http://127.0.0.1:8090/prefetch"
	body, _ := json.Marshal(map[string]interface{}{
		"blocks": blocks,
	})
	resp, err := http.Post(url, "application/json", bytes.NewReader(body))
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("daemon returned %s", resp.Status)
	}
	return nil
}
